import { NDataTable } from "naive-ui";
import type {
  DataTableProps,
  DataTableInst,
  DataTableFilterState,
} from "naive-ui";
import type { HTMLAttributes } from "vue";
import type { BaseComponentType, OmitHTMLAttributes } from "../types";
import { getSlotsDom } from "../utils";

export type DataTableFactoryConstructorType = {
  props?: DataTableProps;
  attrs?: OmitHTMLAttributes<"onLoad">;
  emptySlot?: BaseComponentType;
  loadingSlot?: BaseComponentType;
};
export class DataTableFactory {
  private attrs: OmitHTMLAttributes<"onLoad"> = {};
  private props: DataTableProps = {};
  private emptySlot: BaseComponentType = null;
  private loadingSlot: BaseComponentType = null;
  private domRef: DataTableInst | null = null;
  constructor(data?: DataTableFactoryConstructorType) {
    if (data?.props) this.setProps(data.props);
    if (data?.attrs) this.setAttrs(data.attrs);
    if (data?.emptySlot) this.setEmpty(data.emptySlot);
    if (data?.loadingSlot) this.setLoading(data.loadingSlot);
  }

  setProps(props: DataTableProps) {
    this.props = props;
    return this;
  }

  setAttrs(attrs: HTMLAttributes) {
    this.attrs = attrs;
    return this;
  }

  setEmpty(component: BaseComponentType) {
    this.emptySlot = component;
    return this;
  }

  setLoading(component: BaseComponentType) {
    this.loadingSlot = component;
    return this;
  }
  clearFilters() {
    this.domRef?.clearFilters();
  }
  clearSorter() {
    this.domRef?.clearSorter();
  }
  downloadCsv(options?: { fileName?: string; keepOriginalData?: boolean }) {
    this.domRef?.downloadCsv(options);
  }
  filters(filters: DataTableFilterState | null) {
    this.domRef?.filters(filters);
  }
  page(page: number) {
    this.domRef?.page(page);
  }
  scrollTo(options: {
    left?: number;
    top?: number;
    behavior?: ScrollBehavior;
  }) {
    this.domRef?.scrollTo(options);
  }
  sort(columnKey: string | number | null, order: "ascend" | "descend" | false) {
    if (columnKey !== null) {
      this.domRef?.sort(columnKey, order);
    }
  }
  create() {
    return (
      <NDataTable
        ref={(el: HTMLElement) => {
          this.domRef = el as unknown as DataTableInst;
        }}
        {...this.attrs}
        {...this.props}
      >
        {{
          empty: () => getSlotsDom(this.emptySlot),
          loading: () => getSlotsDom(this.loadingSlot),
        }}
      </NDataTable>
    );
  }
}
